from typing import Tuple, Optional, Dict, Any
from models import db
from models.user import User
from utils.user_errors import (
    UserNotFoundError,
    UserAlreadyExistsError,
    InvalidCredentialsError,
    AccountDeactivatedError,
    ValidationError
)
from utils.logger import get_logger

logger = get_logger(__name__)

class UserService:
    """用户服务类，处理所有用户相关的业务逻辑"""

    def register(self, username: str, email: str, password: str) -> Tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        用户注册
        返回: (成功标志, 消息, 用户数据)
        """
        try:
            # 验证用户名和邮箱是否已存在
            if User.query.filter_by(username=username).first():
                raise UserAlreadyExistsError(f"用户名 '{username}' 已被使用")
            
            if User.query.filter_by(email=email).first():
                raise UserAlreadyExistsError(f"邮箱 '{email}' 已被注册")

            # 验证密码强度
            if len(password) < 6:
                raise ValidationError("密码长度必须至少为6个字符")

            # 创建新用户
            new_user = User(username=username, email=email, password=password)
            db.session.add(new_user)
            db.session.commit()

            logger.info(f"New user registered: {username}")
            return True, "注册成功", new_user.to_dict()

        except (UserAlreadyExistsError, ValidationError) as e:
            logger.warning(f"Registration failed: {str(e)}")
            return False, str(e), None
        except Exception as e:
            logger.error(f"Unexpected error during registration: {str(e)}", exc_info=True)
            db.session.rollback()
            return False, "注册过程中发生错误", None

    def login(self, username: str, password: str) -> Tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        用户登录
        返回: (成功标志, 消息, 用户数据)
        """
        try:
            user = User.query.filter_by(username=username).first()
            
            if not user:
                raise UserNotFoundError()

            if not user.is_active:
                raise AccountDeactivatedError()

            if not user.check_password(password):
                raise InvalidCredentialsError()

            logger.info(f"User logged in: {username}")
            return True, "登录成功", user.to_dict()

        except (UserNotFoundError, AccountDeactivatedError, InvalidCredentialsError) as e:
            logger.warning(f"Login failed for user {username}: {str(e)}")
            return False, str(e), None
        except Exception as e:
            logger.error(f"Unexpected error during login: {str(e)}", exc_info=True)
            return False, "登录过程中发生错误", None

    def get_user_by_id(self, user_id: int) -> Optional[Dict[str, Any]]:
        """
        通过ID获取用户信息
        """
        try:
            user = User.query.get(user_id)
            if user and user.is_active:
                return user.to_dict()
            return None
        except Exception as e:
            logger.error(f"Error fetching user {user_id}: {str(e)}", exc_info=True)
            return None

    def deactivate_account(self, user_id: int) -> Tuple[bool, str]:
        """
        注销用户账户
        返回: (成功标志, 消息)
        """
        try:
            user = User.query.get(user_id)
            if not user:
                raise UserNotFoundError()

            user.deactivate()
            db.session.commit()
            
            logger.info(f"User account deactivated: {user.username}")
            return True, "账户已成功注销"

        except UserNotFoundError as e:
            logger.warning(f"Account deactivation failed: {str(e)}")
            return False, str(e)
        except Exception as e:
            logger.error(f"Error during account deactivation: {str(e)}", exc_info=True)
            db.session.rollback()
            return False, "账户注销过程中发生错误"

    def update_user_info(self, user_id: int, data: Dict[str, Any]) -> Tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        更新用户信息
        返回: (成功标志, 消息, 更新后的用户数据)
        """
        try:
            user = User.query.get(user_id)
            if not user:
                raise UserNotFoundError()

            if not user.is_active:
                raise AccountDeactivatedError()

            # 更新允许修改的字段
            if 'email' in data:
                # 检查新邮箱是否已被使用
                existing_user = User.query.filter_by(email=data['email']).first()
                if existing_user and existing_user.id != user_id:
                    raise UserAlreadyExistsError(f"邮箱 '{data['email']}' 已被使用")
                user.email = data['email']

            if 'password' in data:
                if len(data['password']) < 6:
                    raise ValidationError("新密码长度必须至少为6个字符")
                user.set_password(data['password'])

            db.session.commit()
            logger.info(f"User information updated: {user.username}")
            return True, "用户信息更新成功", user.to_dict()

        except (UserNotFoundError, AccountDeactivatedError, UserAlreadyExistsError, ValidationError) as e:
            logger.warning(f"User update failed: {str(e)}")
            return False, str(e), None
        except Exception as e:
            logger.error(f"Error updating user information: {str(e)}", exc_info=True)
            db.session.rollback()
            return False, "更新用户信息时发生错误", None